using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Threading;
using System.Windows.Forms;
using HslCommunication.Core;

namespace HslCommunication.Controls
{
	/// <summary>
	/// 仪表盘控件类
	/// </summary>
	public class UserGaugeChart : UserControl
	{
		private Color color_gauge_border = Color.DimGray;

		private Pen pen_gauge_border = null;

		private Color color_gauge_pointer = Color.Tomato;

		private Brush brush_gauge_pointer = null;

		private double value_start = 0.0;

		private double value_max = 100.0;

		private double value_current = 0.0;

		private double value_alarm_max = 80.0;

		private double value_alarm_min = 20.0;

		private Pen pen_gauge_alarm = null;

		private int m_version = 0;

		private double value_paint = 0.0;

		private SimpleHybirdLock hybirdLock;

		private Action m_UpdateAction;

		private System.Windows.Forms.Timer timer_alarm_check;

		private bool alarm_check = false;

		private int segment_count = 10;

		private StringFormat centerFormat = null;

		private string value_unit_text = string.Empty;

		private bool text_under_pointer = true;

		private bool isBigSemiCircle = false;

		/// <summary> 
		/// 必需的设计器变量。
		/// </summary>
		private IContainer components = null;

		/// <summary>
		/// 获取或设置仪表盘的背景色
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置仪表盘的背景色")]
		[DefaultValue(typeof(Color), "DimGray")]
		public Color GaugeBorder
		{
			get
			{
				return color_gauge_border;
			}
			set
			{
				pen_gauge_border?.Dispose();
				pen_gauge_border = new Pen(value);
				color_gauge_border = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置指针的颜色
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置仪表盘指针的颜色")]
		[DefaultValue(typeof(Color), "Tomato")]
		public Color PointerColor
		{
			get
			{
				return color_gauge_pointer;
			}
			set
			{
				brush_gauge_pointer?.Dispose();
				brush_gauge_pointer = new SolidBrush(value);
				color_gauge_pointer = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置数值的起始值，默认为0
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置数值的起始值，默认为0")]
		[DefaultValue(0.0)]
		public double ValueStart
		{
			get
			{
				if (value_max <= value_start)
				{
					return value_start + 1.0;
				}
				return value_start;
			}
			set
			{
				value_start = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置数值的最大值，默认为100
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置数值的最大值，默认为100")]
		[DefaultValue(100.0)]
		public double ValueMax
		{
			get
			{
				if (value_max <= value_start)
				{
					return value_start + 1.0;
				}
				return value_max;
			}
			set
			{
				value_max = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置数值的当前值，应该处于最小值和最大值之间
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置数值的当前值，默认为0")]
		[DefaultValue(0.0)]
		public double Value
		{
			get
			{
				return value_current;
			}
			set
			{
				if (ValueStart <= value && value <= ValueMax && value != value_current)
				{
					value_current = value;
					int num = Interlocked.Increment(ref m_version);
					ThreadPool.QueueUserWorkItem(ThreadPoolUpdateProgress, num);
				}
			}
		}

		/// <summary>
		/// 获取或设置数值的上限报警值，设置为超过最大值则无上限报警
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置数值的上限报警值，设置为超过最大值则无上限报警，默认为80")]
		[DefaultValue(80.0)]
		public double ValueAlarmMax
		{
			get
			{
				return value_alarm_max;
			}
			set
			{
				if (ValueStart <= value)
				{
					value_alarm_max = value;
					Invalidate();
				}
			}
		}

		/// <summary>
		/// 获取或设置数值的下限报警值，设置为超过最大值则无上限报警
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置数值的下限报警值，设置为小于最小值则无下限报警，默认为20")]
		[DefaultValue(20.0)]
		public double ValueAlarmMin
		{
			get
			{
				return value_alarm_min;
			}
			set
			{
				if (value <= ValueMax)
				{
					value_alarm_min = value;
					Invalidate();
				}
			}
		}

		/// <summary>
		/// 获取或设置仪表盘的分割段数，最小为2，最大1000
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置仪表盘的分割段数，最小为2，最大1000")]
		[DefaultValue(10)]
		public int SegmentCount
		{
			get
			{
				return segment_count;
			}
			set
			{
				if (value > 1 && value < 1000)
				{
					segment_count = value;
				}
			}
		}

		/// <summary>
		/// 获取或设置仪表盘的单位描述文本
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置仪表盘的单位描述文本")]
		[DefaultValue("")]
		public string UnitText
		{
			get
			{
				return value_unit_text;
			}
			set
			{
				value_unit_text = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置文本是否是指针的下面
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("获取或设置文本是否是指针的下面")]
		[DefaultValue(true)]
		public bool IsTextUnderPointer
		{
			get
			{
				return text_under_pointer;
			}
			set
			{
				text_under_pointer = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 通常情况，仪表盘不会大于半个圆，除非本属性设置为 True
		/// </summary>
		[Browsable(true)]
		[Category("外观")]
		[Description("通常情况，仪表盘不会大于半个圆，除非本属性设置为 True")]
		[DefaultValue(false)]
		public bool IsBigSemiCircle
		{
			get
			{
				return isBigSemiCircle;
			}
			set
			{
				isBigSemiCircle = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 实例化一个仪表盘控件
		/// </summary>
		public UserGaugeChart()
		{
			InitializeComponent();
			pen_gauge_border = new Pen(color_gauge_border);
			brush_gauge_pointer = new SolidBrush(color_gauge_pointer);
			centerFormat = new StringFormat();
			centerFormat.Alignment = StringAlignment.Center;
			centerFormat.LineAlignment = StringAlignment.Center;
			pen_gauge_alarm = new Pen(Color.OrangeRed, 3f);
			pen_gauge_alarm.DashStyle = DashStyle.Custom;
			pen_gauge_alarm.DashPattern = new float[2]
			{
				5f,
				1f
			};
			hybirdLock = new SimpleHybirdLock();
			m_UpdateAction = base.Invalidate;
			timer_alarm_check = new System.Windows.Forms.Timer();
			timer_alarm_check.Tick += Timer_alarm_check_Tick;
			timer_alarm_check.Interval = 1000;
			DoubleBuffered = true;
		}

		private void Timer_alarm_check_Tick(object sender, EventArgs e)
		{
			if (value_current > value_alarm_max || value_current < value_alarm_min)
			{
				alarm_check = !alarm_check;
			}
			else
			{
				alarm_check = false;
			}
			Invalidate();
		}

		private void UserGaugeChart_Load(object sender, EventArgs e)
		{
			timer_alarm_check.Start();
		}

		private void UserGaugeChart_Paint(object sender, PaintEventArgs e)
		{
			if (!Authorization.nzugaydgwadawdibbas())
			{
				return;
			}
			Graphics graphics = e.Graphics;
			graphics.SmoothingMode = SmoothingMode.HighQuality;
			graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
			OperateResult<Point, int, double> centerPoint = GetCenterPoint();
			if (!centerPoint.IsSuccess)
			{
				return;
			}
			Point content = centerPoint.Content1;
			int content2 = centerPoint.Content2;
			float num = Convert.ToSingle(centerPoint.Content3);
			Rectangle rect = new Rectangle(-content2, -content2, 2 * content2, 2 * content2);
			Rectangle rect2 = new Rectangle(-content2 - 5, -content2 - 5, 2 * content2 + 10, 2 * content2 + 10);
			Rectangle rect3 = new Rectangle(-content2 / 3, -content2 / 3, 2 * content2 / 3, 2 * content2 / 3);
			graphics.TranslateTransform(content.X, content.Y);
			graphics.DrawArc(pen_gauge_border, rect3, 0f - num, num * 2f - 180f);
			graphics.DrawArc(pen_gauge_border, rect, num - 180f, 180f - num * 2f);
			graphics.DrawLine(pen_gauge_border, (int)((double)(-(content2 / 3)) * Math.Cos((double)(num / 180f) * Math.PI)), -(int)((double)(content2 / 3) * Math.Sin((double)(num / 180f) * Math.PI)), -(int)((double)(content2 - 30) * Math.Cos((double)(num / 180f) * Math.PI)), -(int)((double)(content2 - 30) * Math.Sin((double)(num / 180f) * Math.PI)));
			graphics.DrawLine(pen_gauge_border, (int)((double)(content2 - 30) * Math.Cos((double)(num / 180f) * Math.PI)), -(int)((double)(content2 - 30) * Math.Sin((double)(num / 180f) * Math.PI)), (int)((double)(content2 / 3) * Math.Cos((double)(num / 180f) * Math.PI)), -(int)((double)(content2 / 3) * Math.Sin((double)(num / 180f) * Math.PI)));
			graphics.RotateTransform(num - 90f);
			int num2 = segment_count;
			for (int i = 0; i <= num2; i++)
			{
				graphics.FillRectangle(rect: new Rectangle(-2, -content2, 3, 7), brush: Brushes.DimGray);
				graphics.DrawString(layoutRectangle: new Rectangle(-50, -content2 + 7, 100, 20), s: (ValueStart + (ValueMax - ValueStart) * (double)i / (double)num2).ToString(), font: Font, brush: Brushes.DodgerBlue, format: centerFormat);
				graphics.RotateTransform((180f - 2f * num) / (float)num2 / 2f);
				if (i != num2)
				{
					graphics.DrawLine(Pens.DimGray, 0, -content2, 0, -content2 + 3);
				}
				graphics.RotateTransform((180f - 2f * num) / (float)num2 / 2f);
			}
			graphics.RotateTransform((0f - (180f - 2f * num)) / (float)num2);
			graphics.RotateTransform(num - 90f);
			Rectangle rectangle = new Rectangle(-36, -(content2 * 2 / 3 - 3), 72, Font.Height + 3);
			if ((value_current > value_alarm_max || value_current < value_alarm_min) && alarm_check)
			{
				graphics.FillRectangle(Brushes.OrangeRed, rectangle);
			}
			if (IsTextUnderPointer)
			{
				graphics.DrawString(Value.ToString(), Font, Brushes.DimGray, rectangle, centerFormat);
				rectangle.Offset(0, Font.Height);
				if (!string.IsNullOrEmpty(UnitText))
				{
					graphics.DrawString(UnitText, Font, Brushes.Gray, rectangle, centerFormat);
				}
			}
			graphics.RotateTransform(num - 90f);
			graphics.RotateTransform((float)((value_paint - ValueStart) / (ValueMax - ValueStart) * (double)(180f - 2f * num)));
			graphics.FillEllipse(rect: new Rectangle(-5, -5, 10, 10), brush: brush_gauge_pointer);
			Point[] points = new Point[5]
			{
				new Point(5, 0),
				new Point(2, -content2 + 40),
				new Point(0, -content2 + 20),
				new Point(-2, -content2 + 40),
				new Point(-5, 0)
			};
			graphics.FillPolygon(brush_gauge_pointer, points);
			graphics.RotateTransform((float)((0.0 - (value_paint - ValueStart)) / (ValueMax - ValueStart) * (double)(180f - 2f * num)));
			graphics.RotateTransform(90f - num);
			if (value_alarm_min > ValueStart && value_alarm_min <= ValueMax)
			{
				graphics.DrawArc(pen_gauge_alarm, rect2, num - 180f, (float)((ValueAlarmMin - ValueStart) / (ValueMax - ValueStart) * (double)(180f - 2f * num)));
			}
			if (value_alarm_max >= ValueStart && value_alarm_max < ValueMax)
			{
				float num3 = (float)((value_alarm_max - ValueStart) / (ValueMax - ValueStart) * (double)(180f - 2f * num));
				graphics.DrawArc(pen_gauge_alarm, rect2, -180f + num + num3, 180f - 2f * num - num3);
			}
			if (!IsTextUnderPointer)
			{
				graphics.DrawString(Value.ToString(), Font, Brushes.DimGray, rectangle, centerFormat);
				rectangle.Offset(0, Font.Height);
				if (!string.IsNullOrEmpty(UnitText))
				{
					graphics.DrawString(UnitText, Font, Brushes.Gray, rectangle, centerFormat);
				}
			}
			graphics.ResetTransform();
		}

		/// <summary>
		/// 获取中心点的坐标
		/// </summary>
		/// <returns></returns>
		private OperateResult<Point, int, double> GetCenterPoint()
		{
			OperateResult<Point, int, double> operateResult = new OperateResult<Point, int, double>();
			if (base.Height <= 35)
			{
				return operateResult;
			}
			if (base.Width <= 20)
			{
				return operateResult;
			}
			operateResult.IsSuccess = true;
			if (!IsBigSemiCircle)
			{
				operateResult.Content2 = base.Height - 30;
				if ((double)(base.Width - 40) / 2.0 > (double)operateResult.Content2)
				{
					operateResult.Content3 = Math.Acos(1.0) * 180.0 / Math.PI;
				}
				else
				{
					operateResult.Content3 = Math.Acos((double)(base.Width - 40) / 2.0 / (double)(base.Height - 30)) * 180.0 / Math.PI;
				}
				operateResult.Content1 = new Point(base.Width / 2, base.Height - 10);
				return operateResult;
			}
			operateResult.Content2 = (base.Width - 40) / 2;
			if (base.Height - 30 < operateResult.Content2)
			{
				operateResult.Content2 = base.Height - 30;
				operateResult.Content3 = Math.Acos(1.0) * 180.0 / Math.PI;
				operateResult.Content1 = new Point(base.Width / 2, base.Height - 10);
				return operateResult;
			}
			int num = base.Height - 30 - operateResult.Content2;
			if (num > operateResult.Content2)
			{
				num = operateResult.Content2;
			}
			operateResult.Content3 = (0.0 - Math.Asin((double)num * 1.0 / (double)operateResult.Content2)) * 180.0 / Math.PI;
			operateResult.Content1 = new Point(base.Width / 2, operateResult.Content2 + 20);
			return operateResult;
		}

		private void ThreadPoolUpdateProgress(object obj)
		{
			try
			{
				int num = (int)obj;
				if (value_paint == value_current)
				{
					return;
				}
				double num2 = Math.Abs(value_paint - value_current) / 10.0;
				if (num2 == 0.0)
				{
					num2 = 1.0;
				}
				while (value_paint != value_current)
				{
					Thread.Sleep(17);
					if (num != m_version)
					{
						break;
					}
					hybirdLock.Enter();
					double num3 = 0.0;
					if (value_paint > value_current)
					{
						double num4 = value_paint - value_current;
						if (num4 > num2)
						{
							num4 = num2;
						}
						num3 = value_paint - num4;
					}
					else
					{
						double num5 = value_current - value_paint;
						if (num5 > num2)
						{
							num5 = num2;
						}
						num3 = value_paint + num5;
					}
					value_paint = num3;
					hybirdLock.Leave();
					if (num == m_version)
					{
						if (base.IsHandleCreated)
						{
							Invoke(m_UpdateAction);
						}
						continue;
					}
					break;
				}
			}
			catch (Exception)
			{
			}
		}

		/// <summary> 
		/// 清理所有正在使用的资源。
		/// </summary>
		/// <param name="disposing">如果应释放托管资源，为 true；否则为 false。</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		/// <summary> 
		/// 设计器支持所需的方法 - 不要修改
		/// 使用代码编辑器修改此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			SuspendLayout();
			base.AutoScaleDimensions = new System.Drawing.SizeF(7f, 17f);
			base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			BackColor = System.Drawing.Color.Transparent;
			Font = new System.Drawing.Font("微软雅黑", 9f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134);
			base.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
			base.Name = "UserGaugeChart";
			base.Size = new System.Drawing.Size(257, 226);
			base.Load += new System.EventHandler(UserGaugeChart_Load);
			base.Paint += new System.Windows.Forms.PaintEventHandler(UserGaugeChart_Paint);
			ResumeLayout(false);
		}
	}
}
